#include "widget.h"
#include "ui_widget.h"

#include <QMouseEvent>
#include <QGraphicsDropShadowEffect>
#include <QLineEdit>
#include <QVector>
#include <QJsonArray>
#include <QJsonObject>
#include <algorithm>
#include <QSqlError>
#include <random>
#include <QList>
#include <QFileDialog>
#include <QMediaMetaData>
#include <memory>
#include <QSystemTrayIcon>
#include <QMenu>
#include <QMessageBox>
#include "qmediaplaylist.h"
#include "volumetool.h"
#include "musiclist.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    initUi(); //初始化界面控件

    initSQLite();

    initMusicList();

    initPlayer();

    connectTheSlots();
}

Widget::~Widget()
{
    delete ui;
}

void Widget::connectTheSlots()
{
    //页面切换
    connect(ui->recm, &BtForm::changeIndex, this, &Widget::setStackWidgetIndex);
    connect(ui->like, &BtForm::changeIndex, this, &Widget::setStackWidgetIndex);
    connect(ui->local, &BtForm::changeIndex, this, &Widget::setStackWidgetIndex);
    connect(ui->recent, &BtForm::changeIndex, this, &Widget::setStackWidgetIndex);

    //最小化窗口
    connect(ui->min, &QPushButton::clicked, this, &Widget::showMinimized);

    //音量调节框
    connect(ui->Volumn, &QPushButton::clicked, this, [=](){
        QPoint point = ui->Volumn->mapToGlobal(QPoint(0, 0));
        QPoint volumeLeftTop = point - QPoint(volumeTool->width()/2, volumeTool->height());

        volumeLeftTop.setX(volumeLeftTop.x() + 12);
        volumeLeftTop.setY(volumeLeftTop.y() + 30);

        volumeTool->move(volumeLeftTop);

        volumeTool->show();
    });

    //添加本地音乐
    connect(ui->addLocal, &QPushButton::clicked, this, [=](){
        QFileDialog* dialog = new QFileDialog(this);
        dialog->setWindowTitle("选择音乐");
        dialog->setDirectory("/Users/wangjiale/music");
        dialog->setNameFilter("*.mp3 *.lrc");
        dialog->setFileMode(QFileDialog::ExistingFiles);
        if(dialog->exec() == QDialog::Accepted)
        {
            QList urls = dialog->selectedUrls();
            ui->localPage->setMusicListType(PageType::LOCAL_PAGE);
            musicList.addMusicsByUrls(urls);
            ui->stackedWidget->setCurrentIndex(2);
            setStackWidgetIndex(2);
            ui->localPage->refresh(musicList);

            for(auto& e : musicList)
            {
                playlist->addMedia(e.getMusicUrl());
            }
            currentIndex = 0;
            ui->localPage->addMusicToPlaylist(musicList, playlist);
            player->setSource(musicList.begin()->getMusicUrl());
        }
    });

    //收藏按钮
    connect(ui->localPage, &CommonPage::updateLikeMusic, this, [=](bool isLike, const QString& musicId){
        updateLikeMusicAndPage(isLike, musicId);
    });

    connect(ui->likePage, &CommonPage::updateLikeMusic, this, [=](bool isLike, const QString& musicId){
        updateLikeMusicAndPage(isLike, musicId);
    });

    connect(ui->recentPage, &CommonPage::updateLikeMusic, this, [=](bool isLike, const QString& musicId){
        updateLikeMusicAndPage(isLike, musicId);
    });

    connect(ui->searchPage, &CommonPage::updateLikeMusic, this, [=](bool isLike, const QString& musicId){
        updateLikeMusicAndPage(isLike, musicId);
    });

    //播放按钮
    connect(ui->play, &QPushButton::clicked, this, [=](){
        onPlayMusic();
    });

    connect(ui->playUp, &QPushButton::clicked, this, [=](){
        playUp();
    });

    connect(ui->playDown, &QPushButton::clicked, this, [=](){
        playDown();
    });

    //切换播放模式
    connect(ui->playMode, &QPushButton::clicked, this, [=](){
        onPlayBackModeClicked();
    });

    //全部播放
    connect(ui->likePage, &CommonPage::playAll, this, &Widget::onPlayAll);
    connect(ui->localPage, &CommonPage::playAll, this, &Widget::onPlayAll);
    connect(ui->recentPage, &CommonPage::playAll, this, &Widget::onPlayAll);
    connect(ui->searchPage, &CommonPage::playAll, this, &Widget::onPlayAll);

    //双击播放
    connect(ui->likePage, &CommonPage::playMusicByIndex, this, &Widget::playClickedMusic);
    connect(ui->localPage, &CommonPage::playMusicByIndex, this, &Widget::playClickedMusic);
    connect(ui->recentPage, &CommonPage::playMusicByIndex, this, &Widget::playClickedMusic);
    connect(ui->searchPage, &CommonPage::playMusicByIndex, this, &Widget::playClickedMusic);

    //静音
    connect(volumeTool, &VolumeTool::silient, this, &Widget::setPlayerSilient);

    //音量调节
    connect(volumeTool, &VolumeTool::setMusicVolume, this, &Widget::setPlayerVolume);

    //音乐当前时长和总时长更新，歌词界面更新
    connect(player, &QMediaPlayer::durationChanged, this, [=](qint64 duration){
        this->duration = duration;

        ui->totalTime->setText(QString("%1:%2").arg(duration / 1000 / 60, 2, 10, QChar('0'))
                                                .arg(duration / 1000 % 60, 2, 10, QChar('0')));
    });

    connect(player, &QMediaPlayer::positionChanged, this, [=](qint64 position){
        this->position = position;

        ui->currentTime->setText(QString("%1:%2").arg(position/1000/60, 2, 10, QChar('0'))
                                     .arg(position/1000%60, 2, 10, QChar('0')));

        ui->progressBar->setMusicSliderValue((float)position / (float)this->duration);

        lrcPage->showLrcWordLine(position);
    });

    //进度条更新音乐进度
    connect(ui->progressBar, &MusicSlider::setMusicSliderPosition, this, [=](float ratio){
        qint64 duration = player->duration() * ratio;
        player->setPosition(duration);
    });

    //自动切换下一首
    connect(player, &QMediaPlayer::mediaStatusChanged, this, &Widget::autoSwitch);

    //歌词页面
    connect(ui->lrcWord, &QPushButton::clicked, this, [=](){
        lrcPage->show();
        lrcAnimation->start();
    });

    //搜索框
    connect(ui->searchBox, &QLineEdit::returnPressed, this, [=](){
        for(auto& e : musicList)
        {
            if(e.getIsSearched())
            {
                e.setIsSearched(false);
            }
        }
        QString music = ui->searchBox->text();
        if(music == "")
        {
            currentPage = ui->localPage;
            setStackWidgetIndex(2);
            ui->localPage->refresh(musicList);
            return;
        }

        auto it = musicList.findMusicByMusicName(music);
        currentPage = ui->searchPage;
        setStackWidgetIndex(4);
        if(it != musicList.end())
        {
            it->setIsSearched(true);
            ui->searchPage->refresh(musicList);
        }
        else
        {
            QMessageBox::information(this, "QQMusic", "没有找到相关音乐捏...");
        }
    });
}

void Widget::initPlayer()
{
    //初始化媒体播放类
    player = new QMediaPlayer(this);
    output = new QAudioOutput(this);
    playlist = new QMediaPlaylist(this);

    //设置默认的播放模式
    playBackMode = Loop;
    ui->playMode->setToolTip("列表循环");

    //添加媒体播放源
    player->setAudioOutput(output);

    //设置默认音量大小
    output->setVolume(0.2);

    srand(0);
}

void Widget::initSQLite()
{
    //打开数据库
    sqlite = QSqlDatabase::addDatabase("QSQLITE");
    sqlite.setDatabaseName("QQMusic.db");
    if(!sqlite.open())
    {
        qDebug() << "sqlite open error";
        return;
    }
    qDebug() << "sqlite open success";


    /*QSqlQuery drop("drop table musicInfo");
    if(drop.exec())
    {
        qDebug() << "done";
    }*/

    //创建表
    QString sql_create_table = "create table if not exists musicInfo(\
                                musicId varchar(200) primary key,\
                                musicName varchar(50),\
                                musicSinger varchar(50),\
                                musicAlbum varchar(30),\
                                duration integer,\
                                isLike boolean,\
                                isHistory boolean,\
                                musicUrl varchar(256)\
                                );";
    QSqlQuery query;
    if(!query.exec(sql_create_table))
    {
        qDebug() << "create table musicInfo fail" << query.lastError().text();
        return;
    }
    qDebug() << "create table musicInfo success";
}

void Widget::initMusicList()
{
    musicList.readFromMusicListDB();

    ui->likePage->setMusicListType(PageType::LIKE_PAGE);
    ui->likePage->refresh(musicList);

    ui->recentPage->setMusicListType(PageType::RECENT_PAGE);
    ui->recentPage->refresh(musicList);

    ui->localPage->setMusicListType(PageType::LOCAL_PAGE);
    ui->localPage->refresh(musicList);
}

QJsonArray& Widget::randomPiction(std::mt19937& g)
{
    QVector<QString> vecImageName1;
    vecImageName1 << "001.png" << "003.png" << "004.png"
                  << "005.png" << "006.png" << "007.png" << "008.png"
                  << "009.png" << "010.png" << "011.png" << "012.png"
                  << "013.png" << "014.png" << "015.png" << "016.png"
                  << "017.png" << "018.png" << "019.png" << "020.png"
                  << "021.png" << "022.png" << "023.png" << "024.png"
                  << "025.png" << "026.png" << "027.png" << "028.png"
                  << "029.png" << "030.png" << "031.png" << "032.png"
                  << "033.png" << "034.png" << "035.png" << "036.png"
                  << "037.png" << "038.png" << "039.png" << "040.png";
    std::shuffle(vecImageName1.begin(), vecImageName1.end(), g);

    //这里好像不支持使用std::random_shuffle，记着取得时候随机取
    //图片+文本采取key-value的方式存储
    objArray = std::make_shared<QJsonArray>(); //json数组
    for(int i = 0; i < vecImageName1.size(); i++)
    {
        //json由多个键值对
        QJsonObject json;
        json.insert("path", ":/images/rec/" + vecImageName1[i]);

        QString text = QString("推荐-%1").arg(i, 3, 10, QChar('0'));
        json.insert("text", text);
        objArray->append(json);
    }

    return *objArray;
}

void Widget::setPlayBackMode(int playBackMode)
{
    this->playBackMode = playBackMode;
}

int Widget::getPlayBackMode()
{
    return playBackMode;
}

void Widget::setRecentMusic(int index)
{
    const QString recentMusic = currentPage->getMusicByIndex(index);
    if(recentMusic == "")
    {
        return;
    }
    auto it = musicList.findMusicByMusicId(recentMusic);
    if(it != musicList.end())
    {
        it->setIsHistory(true);
    }
    ui->recentPage->refresh(musicList);
}

void Widget::setPlayerSilient(bool silient)
{
    if(silient)
    {
        output->setMuted(true);
        volumeTool->setSilent();
    }
    else
    {
        output->setMuted(false);
    }
}

void Widget::setPlayerVolume(int volume)
{
    output->setVolume(volume);
}

void Widget::initUi()
{
    //设置窗口标题
    this->setWindowIcon(QIcon(":/images/tubiao.png"));

    //option + enter
    //f1 for help
    this->setWindowFlag(Qt::FramelessWindowHint, true); //delete the tabColumn
    connect(ui->quit, &QPushButton::clicked, this, [=](){
        musicList.writeToDB();
        sqlite.close();
        close();
    }); // close the window

    //设置背景透明
    setAttribute(Qt::WA_TranslucentBackground, true);

    //添加阴影效果
    QGraphicsDropShadowEffect* shadowEffect = new QGraphicsDropShadowEffect(this);
    shadowEffect->setOffset(0, 0); //设置偏移位置，0，0是围在窗口四周
    shadowEffect->setColor("#000000"); //黑色
    shadowEffect->setBlurRadius(10); //设置阴影大小
    this->setGraphicsEffect(shadowEffect);

    //取消横向拖动条
    ui->scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);

    //设置输入框提示
    ui->searchBox->setPlaceholderText("输入你想找的音乐吧...");

    //设置bodyLeft中的按钮信息
    ui->recm->setIconAndText(":/images/rec.png", "推荐", 0);
    ui->like->setIconAndText(":/images/like.png", "我喜欢", 1);
    ui->local->setIconAndText(":/images/local.png", "本地下载", 2);
    ui->recent->setIconAndText(":/images/recent.png", "最近播放", 3);

    //设置默认页面
    ui->stackedWidget->setCurrentIndex(0);
    currentPage = ui->localPage;
    ui->recm->showAnimation();
    ui->recm->highLighting();

    //更新推荐页面的内容
    std::mt19937 g1(time(0));
    std::mt19937 g2(time(0) + 100);
    ui->recToday->initRecBoxUi(randomPiction(g1), 1);
    ui->supplyMusic->initRecBoxUi(randomPiction(g2), 2);
    ui->recToday->createRecBoxItem();
    ui->supplyMusic->createRecBoxItem();

    //设置commonPage
    //ui->likePage->setMusicListType(PageType::LIKE_PAGE);
    ui->likePage->setCommonPageUi("我喜欢", ":/images/ilikebg.png");

    //ui->localPage->setMusicListType(PageType::LOCAL_PAGE);
    ui->localPage->setCommonPageUi("本地音乐", ":/images/localbg.png");

    //ui->recentPage->setMusicListType(PageType::RECENT_PAGE);
    ui->recentPage->setCommonPageUi("最近播放", ":/images/recentbg.png");

    //音量调节页面
    volumeTool = new VolumeTool(this);
    volumeTool->hide();

    //显示歌词页面
    lrcPage = new LrcPage(this);
    lrcPage->hide();

    //歌词页面显示动画
    lrcAnimation = new QPropertyAnimation(lrcPage, "geometry", this);
    lrcAnimation->setDuration(250);
    lrcAnimation->setStartValue(QRect(10, 10 + lrcPage->height(), lrcPage->width(), lrcPage->height()));
    lrcAnimation->setEndValue(QRect(10, 10, lrcPage->width(), lrcPage->height()));

    //设置搜索页
    ui->searchPage->setMusicListType(PageType::SEARCH_PAGE);
    ui->searchPage->initSearchPage();
}

//实现左键拖拽改变窗口位置的效果
void Widget::mousePressEvent(QMouseEvent* event)
{
    if(Qt::LeftButton == event->button()) //左键拖拽
    {
        //获取窗口左上角在整个屏幕中的位置（全局坐标-局部坐标）
        dragPosition = event->globalPos() - geometry().topLeft();
        isDrag = true;
        return;
    }
    QWidget::mousePressEvent(event); //不需要重写的部分交给父类处理
}

void Widget::setStackWidgetIndex(int id)
{
    ui->stackedWidget->setCurrentIndex(id);

    QList<BtForm*> btFormList = this->findChildren<BtForm*>();
    for(auto& item : btFormList)
    {
        if(item->getPageId() != id)
        {
            item->setOriginalStyleSheet();
            item->hideAnimation();
        }
        else
        {
            item->showAnimation();
            item->highLighting();
        }
    }
    isDrag = false;
}

void Widget::updateLikeMusicAndPage(bool isLike, const QString &musicId)
{
    auto it = musicList.findMusicByMusicId(musicId);
    if(it != musicList.end())
        it->setIsLike(isLike);
    ui->likePage->refresh(musicList);
    ui->localPage->refresh(musicList);
    ui->recentPage->refresh(musicList);
}


void Widget::mouseMoveEvent(QMouseEvent* event)
{
    if(Qt::LeftButton == event->buttons() && isDrag)
    {
        //根据鼠标当前位置设置新的位置
        move(event->globalPos() - dragPosition);
        return;
    }
    QWidget::mouseMoveEvent(event); //不需要重写的部分交给父类处理
}

////////////音乐播放相关////////////

void Widget::onPlayMusic()
{
    if(playlist->isEmpty())
    {
        QMessageBox* message = new QMessageBox(this);
        message->setText("当前没有音乐播放");
        message->show();
    }
    else if(player->playbackState() == QMediaPlayer::PlayingState)
    {
        player->pause();
        ui->play->setStyleSheet("background-image: url(:/images/play3.png);background-position: center center;");
    }
    else if(player->playbackState() == QMediaPlayer::PausedState)
    {
        player->play();
        ui->play->setStyleSheet("background-image: url(:/images/play_on.png);background-position: center center;");
    }
    else if(player->playbackState() == QMediaPlayer::StoppedState)
    {
        player->play();
        ui->play->setStyleSheet("background-image: url(:/images/play_on.png);background-position: center center;");
    }
    else {
        qDebug() << "error occurs in music playing";
    }
}

void Widget::playUp()
{
    QUrl url;
    if(playBackMode == Loop)
    {
        currentIndex++;
        if(currentIndex > playlist->mediaCount() - 1)
        {
            currentIndex = 0;
        }
        setRecentMusic(currentIndex);
        qDebug() << "currentIndex" << currentIndex;
        qDebug() << "mediaCount" << playlist->mediaCount();
        url = playlist->media(currentIndex);
        player->setSource(url);
        player->play();
    }
    else if(playBackMode == Random)
    {
        currentIndex = rand() % (playlist->mediaCount());
        setRecentMusic(currentIndex);
        url = playlist->media(currentIndex);
        player->setSource(url);
        player->play();
    }
    else if(playBackMode == CurrentItemInLoop)
    {
        url = playlist->media(currentIndex);
        player->setSource(url);
        player->play();
    }
    ui->play->setStyleSheet("background-image: url(:/images/play_on.png);background-position: center center;");
    updateMusicInfo();
}

void Widget::playDown()
{   
    if(playBackMode == Loop)
    {
        currentIndex--;
        if(currentIndex < 0)
        {
            currentIndex = playlist->mediaCount() - 1;
        }
        setRecentMusic(currentIndex);
        QUrl url = playlist->media(currentIndex);
        player->setSource(url);
        player->play();
    }
    else if(playBackMode == Random)
    {
        currentIndex = rand() % (playlist->mediaCount());
        QUrl url = playlist->media(currentIndex);
        setRecentMusic(currentIndex);
        player->setSource(url);
        player->play();
    }
    else if(playBackMode == CurrentItemInLoop)
    {
        QUrl url = playlist->media(currentIndex);
        player->setSource(url);
        player->play();
    }
    ui->play->setStyleSheet("background-image: url(:/images/play_on.png);background-position: center center;");
    updateMusicInfo();
}

void Widget::onPlayBackModeClicked()
{
    //列表循环---> 单圈循环---> 随机播放
    //根据当前播放模式，切换下一个播放模式（默认是循环播放）
    if(playBackMode == Loop)
    {
        playBackMode = CurrentItemInLoop;
        ui->playMode->setStyleSheet("background-image:url(:/images/single_play.png); background-position: center center");
        ui->playMode->setToolTip("单曲循环");
    }
    else if(playBackMode == CurrentItemInLoop)
    {
        playBackMode = Random;
        ui->playMode->setStyleSheet("background-image:url(:/images/shuffle_2.png); background-position: center center");
        ui->playMode->setToolTip("随机播放");
    }
    else if(playBackMode == Random)
    {
        playBackMode = Loop;
        ui->playMode->setStyleSheet("background-image:url(:/images/order_play.png); background-position: center center");
        ui->playMode->setToolTip("列表循环");
    }
    else
    {
        qDebug() << "Unknown playbackmode";
    }
}

void Widget::onPlayAll(PageType pageType)
{
    CommonPage* page;

    switch(pageType)
    {
    case LIKE_PAGE:
        page = ui->likePage;
        break;
    case LOCAL_PAGE:
        page = ui->localPage;
        break;
    case RECENT_PAGE:
        page = ui->recentPage;
        break;
    case SEARCH_PAGE:
        page = ui->searchPage;
        break;
    default:
        qDebug() << "未支持的全部播放模式";
    }

    playAllOnCommonPage(page, 0);
    ui->play->setStyleSheet("background-image: url(:/images/play_on.png);background-position: center center;");
}

void Widget::playAllOnCommonPage(CommonPage* page, int index)
{
    currentPage = page;
    playlist->clear();
    //qDebug() << musicList.isEmpty();
    page->addMusicToPlaylist(musicList, playlist);
    qDebug() << playlist->isEmpty() << "<<<<<<";
    player->setSource(playlist->media(index));
    qDebug() << playlist->media(index);
    qDebug() << "<<<<<<<<<<";

    playBackMode = Loop;
    currentIndex = index;
    player->play();

    setRecentMusic(currentIndex);
    updateMusicInfo();
}

void Widget::playClickedMusic(CommonPage* page, int index)
{
    playAllOnCommonPage(page, index);
    ui->play->setStyleSheet("background-image: url(:/images/play_on.png);background-position: center center;");
}

void Widget::autoSwitch(int status)
{
    if(status == QMediaPlayer::EndOfMedia)
    {
        playUp();
    }
}

void Widget::updateMusicInfo()
{
    QMediaMetaData data = player->metaData();
    QVariant imageVariant = data[QMediaMetaData::ThumbnailImage];
    qDebug() << imageVariant << "^^^^^^^^^^^^^";
    qDebug() << "1";

    //更新歌名、歌手
    QString musicId = currentPage->getMusicByIndex(currentIndex);
    auto it = musicList.findMusicByMusicId(musicId);
    QString musicName("未知歌名");
    QString singerName("未知歌手");
    if(it != musicList.end())
    {
        musicName = it->getMusicName();
        singerName = it->getMusicSinger();
    }
    ui->musicName->setText(musicName);
    ui->musicSinger->setText(singerName);

    if(imageVariant.isValid())
    {
        QImage image = imageVariant.value<QImage>();
        ui->musicCover->setPixmap(QPixmap::fromImage(image));
    }
    else
    {
        QString path(":/images/non-music.png");
        ui->musicCover->setPixmap(path);
    }
    ui->musicCover->setScaledContents(true);
    currentPage->updateMusicCover(imageVariant);

    //更新并解析歌词文件路径
    if(it != musicList.end())
    {
        currentLrcFilePath = it->getLrcFilePath();
        lrcPage->parseLrcFile(currentLrcFilePath);
        lrcPage->setMusicInfo(musicName, singerName);
    }

    connect(player, &QMediaPlayer::metaDataChanged, this, [=](){
        if(!playlist->isEmpty())
            updateMusicInfo();
        else
            return;
    });
}

